﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ThreeByte.ActiveDeck.Config;
using ThreeByte.ActiveDeck.Service;
using System.Xml.Linq;
using PowerPoint = Microsoft.Office.Interop.PowerPoint;
using Office = Microsoft.Office.Core;
using ThreeByte.ActiveDeck.Data;
using ThreeByte.Media;
using System.IO;
using ThreeByte.ActiveDeck.AddIn.Content.UserResponse;
using ThreeByte.ActiveDeck.Data.UserResponse;
using log4net;
using ThreeByte.ActiveDeck.Controls.UserResponse;
using ThreeByte.ActiveDeck.AddIn.Controls;


namespace ThreeByte.ActiveDeck.Controls
{
    /// <summary>
    /// Interaction logic for SetupUserResponseControl.xaml
    /// </summary>
    public partial class SetupUserResponseControl : UserControl
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(SetupUserResponseControl));
       
        public event EventHandler<DialogResultEventArgs> Close;
        public CoreConfig Config;
        private IUserResponseConfigurationControl ConfigControl;

        private bool _isGrouped;

        private PowerPoint.Slide _slideHint;
        public PowerPoint.Slide SlideHint {
            get {
                return _slideHint;
            }
            set {
                _slideHint = value;
            }
        }


        public SetupUserResponseControl(CoreConfig config, PowerPoint.Shape currentGraphic = null, bool isGrouped = false) {
            InitializeComponent();

            Config = config;
            _isGrouped = isGrouped;

            //Populate the possible questions
            //TODO: Filter questions from deleted slides....
            List<PageConfig> possibleQuestions = new List<PageConfig>();

            foreach(int slideId in config.SlideIDs) {
                foreach(PageConfig page in config[slideId].Pages) {
                    if(page is MultipleChoiceConfig
                        || page is QuestionConfig
                        || page is CategoriesConfig) {
                            possibleQuestions.Add(page);
                    }
                }
            }

            QuestionList.ItemsSource = possibleQuestions;

            if(_isGrouped) {
                QuestionList.SelectionMode = SelectionMode.Extended;
            }

            //TODO: If we are editing a graphic, then update the UI controls

            ValidateForm();
        }

        private bool IsFormValid() {

            //Decide whether or not, done should be enabled to create/update the graphic config
            if (QuestionList.SelectedItems.Count < 1) {
                return false;
            }

            if(!_isGrouped) {
                if(QuestionList.SelectedItems.Count != 1) {
                    return false;
                }
            }
            return true;
        }

        private void ValidateForm() {
            DoneButton.IsEnabled = IsFormValid();
        
        }


        private void CancelButton_Click(object sender, RoutedEventArgs e) {
            if(Close != null) {
                Close(this, new DialogResultEventArgs(System.Windows.Forms.DialogResult.Cancel));
            }
        }

        private void DoneButton_Click(object sender, RoutedEventArgs e) {
            InsertGraphic();

            if(Close != null) {
                Close(this, new DialogResultEventArgs(System.Windows.Forms.DialogResult.OK));
            }
        }


        private void InsertGraphic() {

            log.Debug("Inserting a user response graphic");

            try {
                //Insert it as a shape
                //TODO: Is there a better way to prevent referencing ActiveWindow?
                PowerPoint.Shape newShape = ConfigControl.InsertUserResponseComponent(Globals.ThisAddIn.Application.ActiveWindow.Selection.SlideRange[1]);
                newShape.Select();
            } catch (Exception ex) {
                log.Error("Cannot Insert Graphic", ex);
            }

        }

        private void QuestionList_SelectionChanged(object sender, SelectionChangedEventArgs e) {
            //Choose the correct type of configuration
            ConfigurationRoot.Children.Clear();

            //Get the currentSlideconfig
            List<PageConfig> configs = new List<PageConfig>();

            foreach(PageConfig pc in QuestionList.SelectedItems) {
                configs.Add(pc);
            }
            //(QuestionList.SelectedItems);
            
            log.DebugFormat("Choose new SlideConfig: {0}", configs[0]);

            try {
                string configurationTypeName = configs[0].GetType().FullName;
                configurationTypeName = configurationTypeName.Replace(".Config.", ".Controls.UserResponse.");
                configurationTypeName = configurationTypeName.Replace("Config", "ResponseConfiguration");
                if(_isGrouped) {
                    configurationTypeName = configurationTypeName.Replace("UserResponse.", "UserResponse.Grouped");
                    log.DebugFormat("configurationTypeName: GroupedMultipleChoiceResponseConfiguration");
                   GroupedMultipleChoiceResponseConfiguration gmcrc = new GroupedMultipleChoiceResponseConfiguration(configs);
                    UserControl configurationControl = (UserControl)gmcrc;

                    ConfigControl = (IUserResponseConfigurationControl)configurationControl;

                    //Then navigate to it
                    ConfigurationRoot.Children.Add(configurationControl);
                } else {
                    log.DebugFormat("configurationTypeName: {0}", configurationTypeName);
                    //use reflection to instantiate a configuration user control
                    Type configurationType = Type.GetType(configurationTypeName, true);
                    UserControl configurationControl = (UserControl)configurationType
                                        .GetConstructor(new Type[] { configs[0].GetType() })
                                        .Invoke(new object[] { configs[0] });

                    ConfigControl = (IUserResponseConfigurationControl)configurationControl;

                    //Then navigate to it
                    ConfigurationRoot.Children.Add(configurationControl);
                }

            } catch (Exception ex) {
                //If the configuration pane doesn't exist, don't freak out
                log.Warn("The configuration pane cannot be instatiated", ex);
            }

            ValidateForm();
        }

    }
}
